//Britable for iTunes

//Acknowledgements:
//Garrett Mace from Macetech (http://macetech.com/store) for the interrupt code (http://docs.macetech.com/doku.php/shiftbrite)
//Benjamin Eckel for the serial protocol (http://blog.datasingularity.com/?p=148)

//This code reads continuosly from the Arduino serial port, waiting for a header byte (111) and then for 25 additional bytes, representing the lit and unlit leds
//I know this could be implemented more efficiently, but I lost my patience after three hours of banging my head against the Processing - Arduino serial communitation.
//As always, any suggetions are welcome
//
//Project homepage: http://code.google.com/p/britable/
//Project blog (in Spanish): http://www.neuronasmuertas.com/britable/
//
//History
//2009-11-15: Initial release

#define latchpin 9 
#define enablepin 10
#define datapin 11
#define clockpin 13

#define iRows 5
#define iCols 5
#define totalLeds iRows * iCols

int iLed[totalLeds][3] = {0};
int mappx[totalLeds] = {0,9,10,19,20,1,8,11,18,21,2,7,12,17,22,3,6,13,16,23,4,5,14,15,24};
char cLedValues[totalLeds] = {0};

void setup() {

  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);

  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);

  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);

  Serial.begin(57600); 
  Serial.flush();
 
}

void loop() {

  SB_WriteLEDData();
  
  if (nextByte() == 111) {
    byte i = 0;
    while (i<25) {  
      cLedValues[i] = nextByte();
      i++;
    } 
    for (int f=0; f<totalLeds; f++) {
      if (cLedValues[f]==1) {
        plot(f%iCols,f/iCols,150,5,0); 
      } 
      else {
        plot(f%iCols,f/iCols,0,0,0); 
      }
    }    
  }

  delay(20);

}

byte nextByte() {
  while(1) {
    if(Serial.available() > 0) {
      byte b =  Serial.read();
      return b;
    }
  }
}

void SB_SendPacket(int SB_CommandMode, int r, int g, int b) {

  if (SB_CommandMode == B01) r =  g = b = 127;

  SPDR = SB_CommandMode << 6 | b>>4;
  while(!(SPSR & (1<<SPIF)));

  SPDR = b<<4 | r>>6;
  while(!(SPSR & (1<<SPIF)));

  SPDR = r << 2 | g>>8;
  while(!(SPSR & (1<<SPIF)));

  SPDR = g;
  while(!(SPSR & (1<<SPIF)));

}

void SB_WriteLEDData() {

  for (int f=0; f<totalLeds; f++) SB_SendPacket(B00, iLed[f][0], iLed[f][1], iLed[f][2]);
  delayMicroseconds(15);
  digitalWrite(latchpin,HIGH);
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

  for (int f=0; f< totalLeds; f++) SB_SendPacket(B01, 0, 0, 0);
  delayMicroseconds(15);
  digitalWrite(latchpin,HIGH);
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

}

void plot(int x, int y, int r, int g, int b){
  iLed[mappx[y*iCols+x]][0] = r;
  iLed[mappx[y*iCols+x]][1] = g;
  iLed[mappx[y*iCols+x]][2] = b;  
}

void background(int c){
  for (int f=0; f<totalLeds; f++){
    iLed[f][0] = iLed[f][1] = iLed[f][2] = c;                       
  }       
}




